package middleware

import (
	"bufio"
	"bytes"
	"encoding/json"
	"io"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/mssola/useragent"

	"go-caipu/pkg/api/jwt"
	"go-caipu/pkg/bus"
	"go-caipu/pkg/services/admin/systemlog"
	"go-caipu/pkg/util"
)

func LoggerToFileMiddleware(bus bus.Bus, j *jwt.JWT) gin.HandlerFunc {
	return func(c *gin.Context) {
		url := c.Request.RequestURI
		//1、静态文件访问不记录
		if !strings.HasPrefix(url, "/api/") && !strings.HasPrefix(url, "/site/") {
			return
		}
		//2、登录、登出不记录
		if strings.Index(url, "api/auth/account") > -1 ||
			strings.Index(url, "api/auth/logout") > -1 {
			return
		}

		//execute time
		startTime := time.Now()
		c.Next()
		endTime := time.Now()

		//3、请求体
		var body string
		switch c.Request.Method {
		case http.MethodPost, http.MethodPut, http.MethodGet, http.MethodDelete:
			var conContent = c.GetHeader("Content-Type")
			if strings.Contains(conContent, "multipart/form-data") {
				body = "文件上传"
				break
			}
			bf := bytes.NewBuffer(nil)
			wt := bufio.NewWriter(bf)
			_, err := io.Copy(wt, c.Request.Body)
			if err != nil {
				log.Fatalf("copy body error, %s", err.Error())
				err = nil
			}
			rb, _ := io.ReadAll(bf)
			c.Request.Body = io.NopCloser(bytes.NewBuffer(rb))
			body = string(rb)
		}

		if c.Request.Method == http.MethodOptions {
			return
		}
		rt, bl := c.Get("result")
		var result = ""
		if bl {
			rb, err := json.Marshal(rt)
			if err != nil {
				log.Fatalf("middleware Logger  json.Marshal result error, %s", err.Error())
			} else {
				result = string(rb)
			}
		}

		ua := useragent.New(c.Request.UserAgent())
		browserName, browserVersion := ua.Browser()
		msg := systemlog.SysOperaLog{
			Os:              ua.OSInfo().Name + " " + ua.OSInfo().Version,
			Address:         "-",
			Browser:         browserName + " " + browserVersion,
			Ip:              util.GetClientIP(c),
			Method:          c.Request.Method,
			RequestBody:     body,
			RequestHeaders:  headerToJSON(c.Request.Header),
			RequestUrl:      c.Request.RequestURI,
			ResponseBody:    result,
			ResponseHeaders: headerToJSON(c.Writer.Header()),
			StatusCode:      2,
			Remark:          "",
			TraceId:         "未设置",
			TimeTaken:       endTime.Sub(startTime).Milliseconds(),
			CreateUser:      "未设置",
			FullPath:        c.FullPath(),
		}
		msg.FullPath = strings.ReplaceAll(msg.FullPath, "/api", "")
		if c.Writer.Status() == 200 {
			msg.StatusCode = 1
		}
		//验证jwt
		tokenString := c.Request.Header.Get(jwt.AUTH)
		msg.CreateBy = 0
		if tokenString != "" {
			claims, err2 := j.ParseToken(tokenString)
			if err2 == nil {
				msg.CreateBy = claims.UserId
			}

		}
		bus.Publish(c.Request.Context(), &msg)
	}
}

// headerToJSON 将 http.Header 转换为 JSON 格式的字符串
func headerToJSON(header http.Header) string {
	// 将 http.Header 转换为 map[string][]string
	headerMap := make(map[string]string)
	for k, v := range header {
		if len(v) > 1 {
			headerMap[k] = util.ArrToString(v)
		}
		if len(v) == 0 {
			headerMap[k] = ""
			continue
		}
		headerMap[k] = v[0]
	}

	// 将 map[string][]string 编码为 JSON 字符串
	jsonData, err := json.MarshalIndent(headerMap, "", "    ")
	if err != nil {
		return ""
	}

	return string(jsonData)
}
